import { AppDispatch } from '@/store'
import { asyncLoginAction } from '@/store/actions/login'
import { LoginFormData } from '@/types/data'
import { Button, Form, Input, Toast } from 'antd-mobile'
// 导入axios提供的错误类型
import { AxiosError } from 'axios'
import { useEffect, useRef, useState } from 'react'
import { useDispatch } from 'react-redux'
import { useLocation, useNavigate } from 'react-router-dom'
import styles from './index.module.scss'
import { InputRef } from 'antd-mobile/es/components/input'
import { getCode } from '@/api/login'

const Login = () => {
  const dispatch = useDispatch<AppDispatch>()
  const nav = useNavigate()
  const location = useLocation() as { state: { from: string } }
  // 获取表单实例
  const [form] = Form.useForm()
  // 获取手机号输入框实例对象
  const mobileRef = useRef<InputRef>(null)

  // 1、登录
  const onFinish = async (formDaata: LoginFormData) => {
    // console.log('formDaata:', formDaata)
    try {
      await dispatch(asyncLoginAction(formDaata))
      Toast.show({
        icon: 'success',
        content: '登陆成功',
      })
      nav(location.state?.from || '/')
    } catch (error) {
      // 给错误信息断言类型，导入axios提供的错误类型AxiosError
      const _error = error as AxiosError<{ message: string }>
      Toast.show({
        icon: 'fail',
        content: _error.response?.data.message,
      })
    }
  }

  /**
   * 发送验证码流程：
   * 1. 给发送验证码绑定点击事件 onClick
   * 2. 在点击事件中，获取手机号的值 => form.getFieldValue('mobile')
   * 3. 在点击事件中，获取手机号输入格式错误 => form.getFieldError('mobile').length > 0
   * 4. 校验手机号格式：如果没有输入 或 格式不正确 => 让手机号输入框获取焦点
   *    通过：getFieldValue(name值)=》获取表单对应name的值 | getFieldError(name值)=》获取表单对应name格式错误
   * 5. 手机号格式校验通过，调用后台接口（参数：手机号），调用运营商接口，发送短信
   * 6. 用户手机号收到短信，填写后进行登录
   */
  // 倒计时秒数
  const [count, setCount] = useState(0)
  // 存储定时器ID
  const timerId = useRef(0)

  // 2、发送验证码
  const sendCode = async () => {
    // 获取手机号
    const mobile = form.getFieldValue('mobile')
    // 获取手机号输入格式错误:string[]
    const isError = form.getFieldError('mobile').length > 0

    if (mobile.trim() === '' || isError) {
      // 手机号没有输入 或者 格式不正确，进入这里，重新获取焦点
      mobileRef.current!.focus()
      return
    }

    // 发送验证码
    try {
      await getCode(mobile)
      /**
       * 开启倒计时流程：
       * 1. 倒计时状态：60s
       * 2. == 发送短信后：立即开启倒计时 ==
       * 3. 倒计时状态等于0：清除定时器
       */
      // 让倒计时时间为60
      setCount(60)
      // 开始倒计时
      // window.setInterval ts中添加window属性调用，解决返回值错误问题
      timerId.current = window.setInterval(() => {
        // 这里通过回调函数语法执行减一，保证获取到正取的count
        setCount((count) => {
          return count - 1
        })
      }, 1000)
    } catch (error) {
      console.log(error)
    }
  }

  // 清理倒计时定时器：1. count === 0结束  2. 组件销毁
  // 检测count的值是否为0，count为0时，清理定时器
  useEffect(() => {
    if (count === 0) {
      clearInterval(timerId.current)
    }
  }, [count])

  // 组件销毁时，清理定时器
  useEffect(() => {
    return () => {
      clearInterval(timerId.current)
    }
  }, [])

  return (
    <div className={styles.root}>
      <div className="login-form">
        <h2 className="title">账号登录</h2>

        <Form form={form} onFinish={onFinish}>
          <Form.Item
            name="mobile"
            rules={[
              { required: true, message: '请输入手机号' },
              {
                pattern: /^1[3-9]\d{9}$/,
                message: '手机号格式错误',
              },
            ]}
            className="login-item">
            <Input ref={mobileRef} placeholder="请输入手机号" />
          </Form.Item>

          <Form.Item
            name="code"
            rules={[
              { required: true, message: '请输入验证码' },
              { len: 6, message: '请输入6位验证码' },
            ]}
            className="login-item"
            extra={
              <span
                // 判断是否开启定时器，没开启绑定事件，开启后去掉事件
                onClick={count === 0 ? sendCode : undefined}
                className="code-extra">
                {/* 判断是否开启定时器，没开启展示 发送验证码，开启后展示倒计时 */}
                {count === 0 ? '发送验证码' : `${count}s后重新获取`}
              </span>
            }>
            <Input placeholder="请输入验证码" autoComplete="off" />
          </Form.Item>

          {/* noStyle 表示不提供 Form.Item 自带的样式 */}
          {/* 
            需求：
            1. 默认表单没有输入或表单输入了有校验错误，按钮转态为禁用
            2. 正确输入了，按钮状态为启用
            流程：
            1. 获取表单实例
            2. 使用实例上的方法：isFieldsTouched | getFieldsError
            3. 判断：表单没有输入或表单输入了是否有校验错误 =》控制按钮的启用或禁用
                  == 条件1-表单中所有的项有没有输入过：==
                  !form.isFieldsTouched(true)=》1. true（都输入过了） 2. false（都没输入过或部分输入了）
                  == 条件2-表单输入了是否有校验错误：==
                  form.getFieldsError().filter(({ errors }) => errors.length)过滤有错误的字段返回新数组，
                  如果新数组长度大于0，说明有格式错误=》按钮禁用 disabled={true}
                  如果新数组长度等于0，说明没有有格式错误=》按钮启用 disabled={false}
          */}
          <Form.Item noStyle shouldUpdate>
            {/* <Button
              block
              type="submit"
              color="primary"
              className="login-submit">
              登 录
            </Button> */}

            {() => (
              <Button
                block
                type="submit"
                color="primary"
                className="login-submit"
                disabled={
                  !form.isFieldsTouched(true) ||
                  !!form.getFieldsError().filter(({ errors }) => errors.length)
                    .length
                }>
                登 录
              </Button>
            )}
          </Form.Item>
        </Form>
      </div>
    </div>
  )
}

export default Login
